home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / mint / shells / tcshsrc.zoo / tcsh / ed.inputl.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-11-25  |  15.5 KB  |  593 lines

  1. /* $Header: /home/hyperion/mu/christos/src/sys/tcsh-6.00/RCS/ed.inputl.c,v 3.4 1991/07/19 15:56:14 christos Exp $ */
  2. /*
  3.  * ed.inputl.c: Input line handling.
  4.  */
  5. /*-
  6.  * Copyright (c) 1980, 1991 The Regents of the University of California.
  7.  * All rights reserved.
  8.  *
  9.  * Redistribution and use in source and binary forms, with or without
  10.  * modification, are permitted provided that the following conditions
  11.  * are met:
  12.  * 1. Redistributions of source code must retain the above copyright
  13.  *    notice, this list of conditions and the following disclaimer.
  14.  * 2. Redistributions in binary form must reproduce the above copyright
  15.  *    notice, this list of conditions and the following disclaimer in the
  16.  *    documentation and/or other materials provided with the distribution.
  17.  * 3. All advertising materials mentioning features or use of this software
  18.  *    must display the following acknowledgement:
  19.  *    This product includes software developed by the University of
  20.  *    California, Berkeley and its contributors.
  21.  * 4. Neither the name of the University nor the names of its contributors
  22.  *    may be used to endorse or promote products derived from this software
  23.  *    without specific prior written permission.
  24.  *
  25.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  26.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  27.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  28.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  29.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  30.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  31.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  32.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  33.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  34.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  35.  * SUCH DAMAGE.
  36.  */
  37. #include "config.h"
  38. RCSID("$Id: ed.inputl.c,v 3.4 1991/07/19 15:56:14 christos Exp $")
  39.  
  40. #include "sh.h"
  41. #include "ed.h"
  42. #include "ed.defns.h"        /* for the function names */
  43. #include "tw.h"            /* for twenex stuff */
  44.  
  45. #define OKCMD (INBUFSIZ+INBUFSIZ)
  46. extern CCRETVAL e_up_hist();
  47. extern CCRETVAL e_expand_history();
  48.  
  49. /* ed.inputl -- routines to get a single line from the input. */
  50.  
  51. extern bool tellwhat;
  52. extern bool MapsAreInited;
  53. extern bool Tty_raw_mode;
  54.  
  55. /* mismatched first character */
  56. #ifdef ALTESC
  57. static Char mismatch[] = {'!', '^', '-', '%', '\0'};
  58. #else
  59. static Char mismatch[] = {'!', '\\', '^', '-', '%', '\0'};
  60. #endif
  61.  
  62. static    int    GetNextCommand    __P((KEYCMD *, Char *));
  63. static    int    SpellLine    __P((int));
  64.  
  65. /* CCRETVAL */
  66. int
  67. Inputl()
  68. {
  69.     CCRETVAL retval;
  70.     KEYCMD  cmdnum = 0;
  71.     extern KEYCMD NumFuns;
  72.     unsigned char tch;        /* the place where read() goes */
  73.     Char    ch;
  74.     int     num;        /* how many chars we have read at NL */
  75.     struct varent *crct = adrof(STRcorrect);
  76.     struct varent *matchbeep = adrof(STRmatchbeep);
  77.     Char   *SaveChar, *CorrChar;
  78.     Char    Origin[INBUFSIZ], Change[INBUFSIZ];
  79.     int     matchval;        /* from tenematch() */
  80.  
  81.     if (!MapsAreInited)        /* double extra just in case */
  82.     ed_InitMaps();
  83.  
  84.     ClearDisp();        /* reset the display stuff */
  85.     ResetInLine();        /* reset the input pointers */
  86.     if (GettingInput)
  87.     MacroLvl = -1;        /* editor was interrupted during input */
  88.  
  89. #ifdef FIONREAD
  90.     if (!Tty_raw_mode && MacroLvl < 0) {
  91.     long    chrs = 0;
  92.  
  93. #ifndef __MINT__
  94. /* MiNT _always_ wants to go into raw mode, so don't bother with the
  95.  * FIONREAD test
  96.  */
  97.     (void) ioctl(SHIN, FIONREAD, (ioctl_t) & chrs);
  98. #endif
  99.     if (chrs == 0) {
  100.         if (Rawmode() < 0)
  101.         return 0;
  102.     }
  103.     }
  104. #endif
  105.  
  106.     GettingInput = 1;
  107.     NeedsRedraw = 0;
  108.  
  109.     if (tellwhat) {
  110.     copyn(InputBuf, WhichBuf, INBUFSIZ);
  111.     LastChar = InputBuf + (LastWhich - WhichBuf);
  112.     Cursor = InputBuf + (CursWhich - WhichBuf);
  113.     tellwhat = 0;
  114.     Hist_num = HistWhich;
  115.     }
  116.     if (Expand) {
  117.     (void) e_up_hist(0);
  118.     Expand = 0;
  119.     }
  120.     Refresh();            /* print the prompt */
  121.  
  122.     for (num = OKCMD; num == OKCMD;) {    /* while still editing this line */
  123. #ifdef DEBUG_EDIT
  124.     if (Cursor > LastChar)
  125.         xprintf("Cursor > LastChar\r\n");
  126.     if (Cursor < InputBuf)
  127.         xprintf("Cursor < InputBuf\r\n");
  128.     if (Cursor > InputLim)
  129.         xprintf("Cursor > InputLim\r\n");
  130.     if (LastChar > InputLim)
  131.         xprintf("LastChar > InputLim\r\n");
  132.     if (InputLim != &InputBuf[INBUFSIZ - 2])
  133.         xprintf("InputLim != &InputBuf[INBUFSIZ-2]\r\n");
  134.     if ((!DoingArg) && (Argument != 1))
  135.         xprintf("(!DoingArg) && (Argument != 1)\r\n");
  136.     if (CcKeyMap[0] == 0)
  137.         xprintf("CcKeyMap[0] == 0 (maybe not inited)\r\n");
  138. #endif
  139.  
  140.     /* if EOF or error */
  141.     if ((num = GetNextCommand(&cmdnum, &ch)) != OKCMD) {
  142.         break;
  143.     }
  144.  
  145.     if (cmdnum >= NumFuns) {/* BUG CHECK command */
  146. #ifdef DEBUG_EDIT
  147.         xprintf("ERROR: illegal command from key 0%o\r\n", ch);
  148. #endif
  149.         continue;        /* try again */
  150.     }
  151.  
  152.     /* now do the real command */
  153.     retval = (*CcFuncTbl[cmdnum]) (ch);
  154.  
  155.     /* save the last command here */
  156.     LastCmd = cmdnum;
  157.  
  158.     /* use any return value */
  159.     switch (retval) {
  160.  
  161.     case CC_REFRESH:
  162.         Refresh();
  163.         /* fall through */
  164.     case CC_NORM:        /* normal char */
  165.         Argument = 1;
  166.         DoingArg = 0;
  167.         /* fall through */
  168.     case CC_ARGHACK:    /* Suggested by Rich Salz */
  169.         /* <rsalz@pineapple.bbn.com> */
  170.         break;        /* keep going... */
  171.  
  172.     case CC_EOF:        /* end of file typed */
  173. #ifdef notdef
  174.         PromptBuf[0] = '\0';
  175. #endif
  176.         num = 0;
  177.         break;
  178.  
  179.     case CC_WHICH:        /* tell what this command does */
  180.         tellwhat = 1;
  181.         copyn(WhichBuf, InputBuf, INBUFSIZ);
  182.         LastWhich = WhichBuf + (LastChar - InputBuf);
  183.         CursWhich = WhichBuf + (Cursor - InputBuf);
  184.         *LastChar++ = '\n';    /* for the benifit of CSH */
  185.         HistWhich = Hist_num;
  186.         Hist_num = 0;    /* for the history commands */
  187.         num = LastChar - InputBuf;    /* number characters read */
  188. #ifdef notdef
  189.         ResetInLine();    /* reset the input pointers */
  190. #endif
  191.         break;
  192.  
  193.     case CC_NEWLINE:    /* normal end of line */
  194.         if (crct && (!Strcmp(*(crct->vec), STRcmd) ||
  195.              !Strcmp(*(crct->vec), STRall))) {
  196.         (void) Strcpy(Origin, InputBuf);
  197.         SaveChar = LastChar;
  198.         if (SpellLine(!Strcmp(*(crct->vec), STRcmd)) == 1) {
  199.             (void) Strcpy(Change, InputBuf);
  200.             *Strchr(Change, '\n') = '\0';
  201.             CorrChar = LastChar;    /* Save the corrected end */
  202.             LastChar = InputBuf;    /* Null the current line */
  203.             Beep();
  204.             printprompt(2, Change);
  205.             Refresh();
  206.             (void) read(SHIN, (char *) &tch, 1);
  207.             ch = tch;
  208.             if (ch != 'y' && ch != ' ') {
  209.             (void) Strcpy(InputBuf, Origin);
  210.             LastChar = SaveChar;
  211.             xprintf("no\n");
  212.             }
  213.             else {
  214.             LastChar = CorrChar;    /* Restore the corrected end */
  215.             xprintf("yes\n");
  216.             }
  217.             flush();
  218.         }
  219.         }            /* end CORRECT code */
  220.         tellwhat = 0;    /* just in case */
  221.         Hist_num = 0;    /* for the history commands */
  222.         num = LastChar - InputBuf;    /* return the number of chars read */
  223.         /*
  224.          * For continuation lines, we set the prompt to prompt 2
  225.          */
  226.         printprompt(1, NULL);
  227. #ifdef notdef
  228.         ResetInLine();    /* reset the input pointers */
  229.         PromptBuf[0] = '\0';
  230. #endif
  231.         break;
  232.  
  233.     case CC_CORRECT:
  234.         if (tenematch(InputBuf, INBUFSIZ, Cursor - InputBuf,
  235.               SPELL) < 0)
  236.         Beep();        /* Beep = No match/ambiguous */
  237.         if (NeedsRedraw) {
  238.         ClearLines();
  239.         ClearDisp();
  240.         NeedsRedraw = 0;
  241.         }
  242.         Refresh();
  243.         Argument = 1;
  244.         DoingArg = 0;
  245.         break;
  246.  
  247.     case CC_CORRECT_L:
  248.         if (SpellLine(FALSE) < 0)
  249.         Beep();        /* Beep = No match/ambiguous */
  250.         if (NeedsRedraw) {
  251.         ClearLines();
  252.         ClearDisp();
  253.         NeedsRedraw = 0;
  254.         }
  255.         Refresh();
  256.         Argument = 1;
  257.         DoingArg = 0;
  258.         break;
  259.  
  260.  
  261.     case CC_COMPLETE:
  262.         if (adrof(STRautoexpand))
  263.         (void) e_expand_history(0);
  264.         /*
  265.          * Modified by Martin Boyer (gamin@ireq-robot.hydro.qc.ca):
  266.          * A separate variable now controls beeping after
  267.          * completion, independently of autolisting.
  268.          */
  269.         switch (matchval = 
  270.             tenematch(InputBuf, INBUFSIZ, Cursor-InputBuf, RECOGNIZE)) {
  271.         case 1:
  272.         if (non_unique_match && matchbeep &&
  273.             (Strcmp(*(matchbeep->vec), STRnotunique) == 0))
  274.             Beep();
  275.         break;
  276.         case 0:
  277.         if (matchbeep) {
  278.             if (Strcmp(*(matchbeep->vec), STRnomatch) == 0 ||
  279.             Strcmp(*(matchbeep->vec), STRambiguous) == 0 ||
  280.             Strcmp(*(matchbeep->vec), STRnotunique) == 0)
  281.             Beep();
  282.         }
  283.         else
  284.             Beep();
  285.         break;
  286.         default:
  287.         if (matchval < 0) {    /* Error from tenematch */
  288.             Beep();
  289.             break;
  290.         }
  291.         if (matchbeep) {
  292.             if ((Strcmp(*(matchbeep->vec), STRambiguous) == 0 ||
  293.              Strcmp(*(matchbeep->vec), STRnotunique) == 0))
  294.             Beep();
  295.         }
  296.         else
  297.             Beep();
  298.         /*
  299.          * Addition by David C Lawrence <tale@pawl.rpi.edu>: If an 
  300.          * attempted completion is ambiguous, list the choices.  
  301.          * (PWP: this is the best feature addition to tcsh I have 
  302.          * seen in many months.)
  303.          */
  304.         if (adrof(STRautolist)) {
  305.             PastBottom();
  306.             (void) tenematch(InputBuf, INBUFSIZ, Cursor-InputBuf, LIST);
  307.         }
  308.         break;
  309.         }
  310.         if (NeedsRedraw) {
  311.         PastBottom();
  312.         ClearLines();
  313.         ClearDisp();
  314.         NeedsRedraw = 0;
  315.         }
  316.         Refresh();
  317.         Argument = 1;
  318.         DoingArg = 0;
  319.         break;
  320.  
  321.     case CC_LIST_CHOICES:
  322.         /* should catch ^C here... */
  323.         if (tenematch(InputBuf, INBUFSIZ, Cursor - InputBuf, LIST) < 0)
  324.         Beep();
  325.         Refresh();
  326.         Argument = 1;
  327.         DoingArg = 0;
  328.         break;
  329.  
  330.     case CC_LIST_GLOB:
  331.         if (tenematch(InputBuf, INBUFSIZ, Cursor - InputBuf, GLOB) < 0)
  332.         Beep();
  333.         Refresh();
  334.         Argument = 1;
  335.         DoingArg = 0;
  336.         break;
  337.  
  338.     case CC_EXPAND_GLOB:
  339.         if (tenematch(InputBuf, INBUFSIZ, Cursor - InputBuf,
  340.               GLOB_EXPAND) <= 0)
  341.         Beep();        /* Beep = No match */
  342.         if (NeedsRedraw) {
  343.         ClearLines();
  344.         ClearDisp();
  345.         NeedsRedraw = 0;
  346.         }
  347.         Refresh();
  348.         Argument = 1;
  349.         DoingArg = 0;
  350.         break;
  351.  
  352.     case CC_EXPAND_VARS:
  353.         if (tenematch(InputBuf, INBUFSIZ, Cursor - InputBuf,
  354.               VARS_EXPAND) <= 0)
  355.         Beep();        /* Beep = No match */
  356.         if (NeedsRedraw) {
  357.         ClearLines();
  358.         ClearDisp();
  359.         NeedsRedraw = 0;
  360.         }
  361.         Refresh();
  362.         Argument = 1;
  363.         DoingArg = 0;
  364.         break;
  365.  
  366.     case CC_HELPME:
  367.         xputchar('\n');
  368.         /* should catch ^C here... */
  369.         (void) tenematch(InputBuf, INBUFSIZ, LastChar - InputBuf,
  370.                  PRINT_HELP);
  371.         Refresh();
  372.         Argument = 1;
  373.         DoingArg = 0;
  374.         break;
  375.  
  376.     case CC_FATAL:        /* fatal error, reset to known state */
  377. #ifdef DEBUG_EDIT
  378.         xprintf("*** editor fatal ERROR ***\r\n\n");
  379. #endif                /* DEBUG_EDIT */
  380.         /* put (real) cursor in a known place */
  381.         ClearDisp();    /* reset the display stuff */
  382.         ResetInLine();    /* reset the input pointers */
  383.         Refresh();        /* print the prompt again */
  384.         Argument = 1;
  385.         DoingArg = 0;
  386.         break;
  387.  
  388.     case CC_ERROR:
  389.     default:        /* functions we don't know about */
  390.         DoingArg = 0;
  391.         Argument = 1;
  392.         Beep();
  393.         flush();
  394.         break;
  395.     }
  396.     }
  397.     (void) Cookedmode();    /* make sure the tty is set up correctly */
  398.     GettingInput = 0;
  399.     flush();            /* flush any buffered output */
  400.     return num;
  401. }
  402.  
  403. void
  404. PushMacro(str)
  405.     Char   *str;
  406. {
  407.     if (str != NULL && MacroLvl + 1 < MAXMACROLEVELS) {
  408.     MacroLvl++;
  409.     KeyMacro[MacroLvl] = str;
  410.     }
  411.     else {
  412.     Beep();
  413.     flush();
  414.     }
  415. }
  416.  
  417. static int
  418. GetNextCommand(cmdnum, ch)
  419.     KEYCMD *cmdnum;
  420.     register Char *ch;
  421. {
  422.     KEYCMD  cmd = 0;
  423.     int     num;
  424.     Char   *str;
  425.  
  426.     for (; cmd == 0 || cmd == F_XKEY;) {
  427.     if ((num = GetNextChar(ch)) != 1) {    /* if EOF or error */
  428.         return num;
  429.     }
  430. #ifdef    KANJI
  431.     if (*ch & META) {
  432.         MetaNext = 0;
  433.         cmd = CcViMap[' '];
  434.         break;
  435.     }
  436.     else
  437. #endif                /* KANJI */
  438.     if (MetaNext) {
  439.         MetaNext = 0;
  440.         *ch |= META;
  441.     }
  442.     cmd = CurrentKeyMap[(unsigned char) *ch];
  443.     if (cmd == F_XKEY) {
  444.         if (GetXkey(ch, &str))
  445.         cmd = (KEYCMD) * str;
  446.         else
  447.         PushMacro(str);
  448.     }
  449.     if (!AltKeyMap) {
  450.         CurrentKeyMap = CcKeyMap;
  451.     }
  452.     }
  453.     *cmdnum = cmd;
  454.     return OKCMD;
  455. }
  456.  
  457. int
  458. GetNextChar(cp)
  459.     register Char *cp;
  460. {
  461.     register int num_read;
  462. #if defined(EWOULDBLOCK) || (defined(POSIX) && defined(EAGAIN))
  463. # if defined(FIONBIO) || (defined(F_SETFL) && defined(O_NDELAY))
  464. #  define TRY_AGAIN
  465.     int     tried = 0;
  466. # endif                /* FIONBIO || (F_SETFL && O_NDELAY) */
  467. #endif                /* EWOULDBLOCK || (POSIX && EAGAIN) */
  468.     unsigned char tcp;
  469.  
  470.     for (;;) {
  471.     if (MacroLvl < 0) {
  472.         if (!Load_input_line())
  473.         break;
  474.     }
  475.     if (*KeyMacro[MacroLvl] == 0) {
  476.         MacroLvl--;
  477.         continue;
  478.     }
  479.     *cp = *KeyMacro[MacroLvl]++ & CHAR;
  480.     if (*KeyMacro[MacroLvl] == 0) {    /* Needed for QuoteMode On */
  481.         MacroLvl--;
  482.     }
  483.     return (1);
  484.     }
  485.  
  486.     if (Rawmode() < 0)        /* make sure the tty is set up correctly */
  487.     return 0;        /* oops: SHIN was closed */
  488.  
  489.     while ((num_read = read(SHIN, (char *) &tcp, 1)) == -1)
  490.     switch (errno) {
  491.         /*
  492.          * Someone might have set our file descriptor to non blocking From
  493.          * Gray Watson (gray%antr.uucp@med.pitt.edu), Thanks!!!
  494.          */
  495. #ifdef EWOULDBLOCK
  496.     case EWOULDBLOCK:
  497. #endif                /* EWOULDBLOCK */
  498. #if defined(POSIX) && defined(EAGAIN)
  499. # if defined(EWOULDBLOCK) && EAGAIN != EWOULDBLOCK
  500.     case EAGAIN:
  501. # endif                /* EWOULDBLOCK && EAGAIN != EWOULDBLOCK */
  502. #endif                /* POSIX && EAGAIN */
  503. #ifdef TRY_AGAIN
  504.         if (!tried) {
  505. # if defined(F_SETFL) && defined(O_NDELAY)
  506.         (void) fcntl(SHIN, F_SETFL,
  507.                  fcntl(SHIN, F_GETFL, 0) & ~O_NDELAY);
  508. # endif                /* F_SETFL && O_NDELAY */
  509. # ifdef FIONBIO
  510.         (void) ioctl(SHIN, FIONBIO, (ioctl_t) & tried);
  511. # endif                /* FIONBIO */
  512.         tried = 1;
  513.         break;
  514.         }
  515.         *cp = tcp;
  516.         return (num_read);
  517. #endif /* TRY_AGAIN */
  518. #ifdef _SEQUENT_
  519.     case EBADF:
  520. #endif                /* _SEQUENT_ */
  521.     case EINTR:
  522.         break;
  523.     default:
  524.         xprintf("GetNextChar(): errno == %d\n", errno);
  525.         *cp = tcp;
  526.         return num_read;
  527.     }
  528.     *cp = tcp;
  529.     return num_read;
  530. }
  531.  
  532. /*
  533.  * SpellLine - do spelling correction on the entire command line
  534.  * (which may have trailing newline).
  535.  * If cmdonly is set, only check spelling of command words.
  536.  * Return value:
  537.  * -1: Something was incorrectible, and nothing was corrected
  538.  *  0: Everything was correct
  539.  *  1: Something was corrected
  540.  */
  541. static int
  542. SpellLine(cmdonly)
  543.     int     cmdonly;
  544. {
  545.     int     endflag, matchval;
  546.     Char   *argptr, *OldCursor, *OldLastChar;
  547.  
  548.     OldLastChar = LastChar;
  549.     OldCursor = Cursor;
  550.     argptr = InputBuf;
  551.     endflag = 1;
  552.     matchval = 0;
  553.     do {
  554.     while (ismeta(*argptr) || iscmdmeta(*argptr))
  555.         argptr++;
  556.     for (Cursor = argptr;
  557.          *Cursor != '\0' && !ismeta(*Cursor) && !iscmdmeta(*Cursor);
  558.          Cursor++);
  559.     if (*Cursor == '\0') {
  560.         Cursor = LastChar;
  561.         if (LastChar[-1] == '\n')
  562.         Cursor--;
  563.         endflag = 0;
  564.     }
  565. #ifdef ALTESC
  566.     if (!Strchr(mismatch, *argptr) && *argptr != escchar &&
  567. #else
  568.     if (!Strchr(mismatch, *argptr) &&
  569. #endif
  570.         (!cmdonly || starting_a_command(argptr, InputBuf))) {
  571.         switch (tenematch(InputBuf, INBUFSIZ, Cursor - InputBuf, SPELL)) {
  572.         case 1:        /* corrected */
  573.         matchval = 1;
  574.         break;
  575.         case -1:        /* couldn't be corrected */
  576.         if (!matchval)
  577.             matchval = -1;
  578.         break;
  579.         default:        /* was correct */
  580.         break;
  581.         }
  582.         if (LastChar != OldLastChar) {
  583.         if (argptr < OldCursor)
  584.             OldCursor += (LastChar - OldLastChar);
  585.         OldLastChar = LastChar;
  586.         }
  587.     }
  588.     argptr = Cursor;
  589.     } while (endflag);
  590.     Cursor = OldCursor;
  591.     return matchval;
  592. }
  593.